package com.marktotop.aspect;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.marktotop.annotation.LogAnnotation;
import com.marktotop.entity.system.Log;
import com.marktotop.service.ILogService;
import com.marktotop.utils.AddressUtil;
import com.marktotop.utils.HttpContextUtil;
import com.marktotop.utils.IPUtil;
import com.marktotop.vo.system.ActiveUserVO;
import org.apache.shiro.SecurityUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;

/**
 * LogAspect - 日志切面
 *
 *     @Aspect 定义通知和切点的关系
 *
 *
 * @author WXLD
 * @Data 2021/7/8
 * @Since 1.0
 */
@Component
@Aspect
public class LogAspect {

    @Autowired
    private ILogService logService;

    @Pointcut("@annotation(com.marktotop.annotation.LogAnnotation)")
    public void pt(){}

    @Around("pt()")
    public Object log(ProceedingJoinPoint joinPoint) throws Throwable {
        long beginTime = System.currentTimeMillis();
        // 执行方法
        Object result = joinPoint.proceed();
        // 记录日志
        recordLog(joinPoint,beginTime);

        return result;

    }

    /**
     * 记录日志 实现
     *
     * @param joinPoint 切点
     * @param beginTime 开始执行时间
     */
    private void recordLog(ProceedingJoinPoint joinPoint, long beginTime) throws JsonProcessingException {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        LogAnnotation logAnnotation = method.getAnnotation(LogAnnotation.class);
        // 创建 log对象
        Log newLog = new Log();
        // 请求的方法名（全类名）
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = signature.getName();
        // 请求的参数
        Object[] args = joinPoint.getArgs();
        ObjectMapper objectMapper = new ObjectMapper();
        String params = "无参数";
        if (args.length > 0){
            params = objectMapper.writeValueAsString(args[0]);
        }
        // 获取request 设置IP地址 、 请求方式 、 地理位置
        HttpServletRequest request = HttpContextUtil.getHttpServletRequest();
        // 请求方式
        String requestMethod = request.getMethod();
        // IP
        String ipAddr = IPUtil.getIpAddr(request);
        //地理位置
        String cityInfo = AddressUtil.getCityInfo(ipAddr);
        // 获得当前登录用户
        ActiveUserVO activeUser= (ActiveUserVO) SecurityUtils.getSubject().getPrincipal();

        newLog.setUsername(activeUser.getUser().getUsername())
                .setModule(logAnnotation.module())
                .setOperation(logAnnotation.operator())
                .setMethod(className + "." + methodName + "()")
                .setMethodType(requestMethod)
                .setParams(params)
                .setIp(ipAddr)
                .setLocation(cityInfo)
                .setCreateTime(new Date())
                .setTime(System.currentTimeMillis() - beginTime);
        // 保存日志
        logService.saveLog(newLog);
    }

}
